0%

准备工作:

工具:buu上的pikachu或者自己搭建的dvwa

burpsuite(其他抓包工具)

burp相关模块的介绍

图片

proxy:通过设置代理,拦截浏览器对网站发送的请求抓包

图片

Intruder:通过对抓包的数据包以变量的方式自定义参数,根据相应策略进行自动化的重放

在这个模块中比较重要的是Pasitions选项卡:

指定需要暴力破解的参数,并设置成变量,同时选择攻击模式

  • Sniper:设置一个payload,先将第一个变量使用字典进行测试,然后在将第二个变量使用字典进行测试
  • Battering ram:设置一个payload,所有的变量一起用字典内容被替换,然后一起尝试
  • Ptichfork:每个变量设置一个payload,分别使用对应的字典对变量进行同时替换
  • Cluster bomb:需要为每一个变量设置一个payload,分别使用字典内容组合对变量进行替换
    以上就是我们的准备工作

正文:

先看下提示,可获知正确的三个用户名和密码组合

图片

首先对网站做一个尝试性的登陆,用户名和密码随意输入

图片

提示我们用户名或者密码不存在,然后我们在burp里查看抓包

图片

将其发送至Instruder模块,对username以及password这两个变量设置参数,并载入相关的字典或者我们自己输入的一些密码用户名

图片

图片

如果说Burp是专业版的话,还可以对并发数进行设置(免费版不能),适当提升并发数可以增加我们爆破的效率(当然有些网站会对高并发进行限制)

图片

然后开始爆破

图片

一般来说可以根据返回的数据包长度来确认是否爆破成功,因为大多数攻击是失败的,数据包长度是一样的,而成功的数据包长度就会与之不同

图片

over.

暴力破解=连续性尝试+字典+自动化

其实就是瞎猜,但是一个有效的字典会大大提高破解的效率

  • 常用的账号密码(弱口令),比如常见的用户名/密码top100
  • 互联网上被脱裤的账号密码
  • 使用指定的字符使用工具按照指定的规则进行排列组合算法生成的密码

    Burte Force(暴力破解)概述

“暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取. 其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果.为了提高效率,暴力破解一般会使用带有字典的工具来进行自动化操作。

理论上来说,大多数系统都是可以被暴力破解的,只要攻击者有足够强大的计算能力和时间,所以断定一个系统是否存在暴力破解漏洞,其条件也不是绝对的.我们说一个web应用系统存在暴力破解漏洞,一般是指该web应用系统没有采用或者采用了比较弱的认证安全策略,导致其被暴力破解的“可能性”变的比较高。 这里的认证安全策略, 包括:

1.是否要求用户设置复杂的密码;

2.是否每次认证都使用安全的验证码或者手机otp;

3.是否对尝试登录的行为进行判断和限制(如:连续5次错误登录,进行账号锁定或IP地址锁定等);

4.是否采用了双因素认证;…等等。

如果一个网站没有对登陆接口实施了防暴力破解的措施,或者实施了不合理的措施,就可以称该网站存在暴力破解的相关漏洞,但暴力破解的成功率并不是百分之一百(你的计算机是天河一号当我没说,你牛逼),所以有些网站管理员会忽视其网站的暴力破解漏洞,因为经过各种限制后,通过爆破所花费的时间成本已经远远大于了我们所能承受的

爆破的测试流程

  1. 确认登陆接口的脆弱性:
    确认目标是否存在漏洞(即存在的可能性)比如:尝试登陆—抓包,观察相关验证元素和response信息,判断是否存在可能

  2. 对字典进行优化:
    根据实际情况对字典进行优化,提高爆破的效率

  3. 工具自动化操作

配置相关的自动化工具(比如线程,超时时间,重试次数)

字典的优化过程

  • 技巧一:

    对目标站点进行注册,获取账号密码的一些限制,比如该站点要求密码必须6位以上,字母数字组合,则有根据要求优化字典
    
  • 技巧二:
    如果爆破的是后台,往往管理员账号比较具有特殊性,比如admin/administrator/root,可以使用这三个账号+任意密码尝试登陆,查看返回的结果,确认用户名

比如:

  • 输入xxx/aaa返回“用户名或密码错误”
  • 输入admin/bbb返回“密码错误”,则可以确认用户名为admin
    根据以上流程就可以只对密码进行爆破,提高效率。

对不起,真的对不起。

我诚挚地向你道歉。

我没能如你期望的那样成为一名光荣的科学家,

我没能在学术的海洋中奋力遨游,没能为美好的世界做出贡献。

更没有研究出长生不老药,让我们的祖母永远存在。

对不起,真的对不起。

我诚挚地向你道歉。

我没有埋头苦读点灯夜战,也没有嬉笑打闹享受青春,

我只是进入了一个一般的高中,上了个一般的大学,找了个一般的工作。

慵懒散漫,傲慢呆滞。理所当然,我成为了一个一般的人。

对不起,真的对不起。

我诚挚地向你道歉。

我没能让你拥有那份草莓蛋糕一样的爱情,

不是失去,不是拒绝,不是刻骨铭心的记忆

而是我沉吟许久,故作轻松地没有开口。

对不起,真的对不起。

我诚挚地向你道歉。

我甚至没能足够善良,足够勇敢,

我在地铁上看着老人摇晃着,却连让座的意愿都已消失,

我的自私和虚伪,令人尖叫。

对不起,真的对不起。

我诚挚地向你道歉。

让白天鹅和丑小鸭绑在一起,

我们看着现实的戏剧发笑,又看着戏剧的现实流泪。

你假装不在乎,我假装很快乐,我们假装拥有一个光明的未来。

在命运的轨迹下苟且偷生,涣然而不自知。

对不起,真的对不起。

我诚挚地向你道歉。

我没能拥有很多财富,让父母享受生活。

我甚至在异乡连三尺立锥之地,都无法拥有。

没有事业,没有人脉,没有积蓄,

只有一夜又一夜,一年又一年,一岁又一岁。

不知悲欢。

对不起,真的对不起。

我诚挚地向你道歉。

二十多年过去了,

我没能成为我自己

熟悉的HGAME,花了几天把web.misc.crypto,还有几道签到题做了,这里做个记录

MISC

欢迎欢迎!热烈欢迎!

签到题,公众号发个消息就有

图片

这个压缩包有点麻烦

图片

拿到后是一个压缩包图片

告诉我们纯数字的6位密码是不安全的这里尝试直接暴力破解得到密码

图片

获得密码后打开readme获得如下提示

图片

再查看另外一个可知是一个密码本即字典,采用字典破解图片

获得如下密码&-`;qpCKliw2yTR\

打开后又有一个readme,打开

图片

而且发现这两者的crc是相同的,

图片

可以尝试采取明文攻击,注意这里提示了要以store模式进行

图片

这里压缩等级选择仅存储,然后进行明文攻击,慢慢等待就可以。然后获得一张图片

图片

拉进010发现里面有压缩包,binwalk分离出来,结果还是有密码的,把压缩包拉进010,发现存在伪加密,改一下就结束了,然后获得flag

图片

好康的流量

下载获得一个流量,拉进wireshark,发现存在base64

图片

加上题目名字是涩图,且下面的url解码出来是涩图.png,采取base64转图片

获得一张图片,用stegslove打开,发现一半flag

图片

接着查看lsb,这次是竖着的所以有点小坑,发现另一半

图片

组合在一起就行

群青(其实是幽灵东京)

打开网址是一首歌,另存到桌面上,用au打开,发现是这首歌的作者Yoasobi

再把这首歌拉进010看,发现有个silenteye提示,用silenteye解密,并用刚才获得的组合名密码解密

图片

获得另外一个音频,不过这个很刺耳,有点类似无线电,网络查询资料知道有道sctf2020的无线电考点基本一样,用安卓软件robot36直接一把梭了

图片

扫出来就是flag

CRYPTO

Easy RSA

图片

打开附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from math import gcd
from random import randint
from gmpy2 import next_prime
from Crypto.Util.number import getPrime
from secret import flag

def encrypt(c):
    p = getPrime(8)
    q = getPrime(8)
    e = randint(0, p * q)
    while gcd(e, (p - 1) * (q - 1)) != 1:
        e = int(next_prime(e))
    return e, p, q, pow(ord(c), e, p * q)

if __name__ == '__main__':
    print(list(map(encrypt, flag)))
    # [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]

这个RSA也确实简单,大致来看这道题可以不看成rsa就看成是到别的题实际上就是求每组的chr(C),c是个ASCII    从可以显示的ASCII(32,127)中一个一个匹配过去,暴力   只要匹配上就输出
图片

写个jio本就可以了

import gmpy2

secret = [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]

1
2
3
4
5
6
7
8
9
10
11
12
13
flag = ""
for m in range(38):
#if 8 == 8 :
    e = secret[m][0]
    p = secret[m][1]
    q = secret[m][2]
    i = secret[m][3]
    lam = p*q
    for c in range(32,127):
            if i == gmpy2.powmod(c, e, lam):
                flag += chr(c)
print(flag)
print(len(flag))

Matryoshka

图片

1
⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠤⠤⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠤⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠨⠨⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠤⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠨⠌⠨⠨⠨⠤⠤⠌⠤⠤⠨⠨⠤⠤⠌⠤⠤⠤⠨⠨⠌⠤⠨⠨⠨⠨⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠨⠨⠨⠨⠤⠌⠤⠤⠨⠨⠤⠤⠌⠨⠨⠨⠨⠤⠌⠤⠨⠨⠨⠨

打开给了一串很像盲文的东西,直接拿去解码没用,仔细观察只有三种图案组成,考虑为摩斯,解码有点迹象,但依旧不像有用的信息,查看提示,纸条背面,考虑是先逆序再摩斯
得到一串ascii(十六进制)

1
46,66,42,75,66,45,46,6e,6d,4c,73,36,44,33,73,69,59,74,4c,36,58,32,70,34,69,4e,30,63,64,53,6c,79,6b,6d,39,72,51,4e,39,6f,4d,53,31,6a,6b,73,39,72,4b,32,52,36,6b,4c,38,68,6f,72,30,3d

接下来就直接用工具一把梭了
图片

English Novel

下载后得明文和密文以及加密脚本

1
2
3
4
5
6
7
8
9
10
11
def encrypt(data, key):
    assert len(data) <= len(key)
    result = ""
    for i in range(len(data)):
        if data[i].isupper():
            result += chr((ord(data[i]) - ord('A') + key[i]) % 26 + ord('A'))
        elif data[i].islower():
            result += chr((ord(data[i]) - ord('a') + key[i]) % 26 + ord('a'))
        else:
            result += data[i]
    return result

很明显的维吉尼亚加密,去看明文和密文已经打乱顺序,并未按照他给的顺序排列,虽然通过大小排序或者其他方法也能匹配到,理论上是可以找一对不是特别短的明文的和密文手算获得密钥然后去用在线解密就行。但是这里我还是请教了其他师傅,采取了脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
keylis = [-1] * 44
flag_cip = "klsyf{W0_j0v_ca0z_'Ks0ao-bln1qstxp_juqfqy'?}"
cip_list = [open('./encrypt/part'+str(i)+'.txt', 'r').read(44) for i in range(409)]
msg_list = [open('./original/part'+str(i)+'.txt', 'r').read(44) for i in range(409)]

while -1 in keylis:
    for cip in cip_list:
        for msg in msg_list:
            flag = True
            for i in range(44):
                if (cip[i].islower() ^ msg[i].islower()) or \
                    (cip[i].isupper() ^ msg[i].isupper()) or \
                        ((cip[i].isupper() or cip[i].islower()) ^ (msg[i].isupper() or msg[i].islower())):
                    flag = False
                    break
            if flag:
                for i in range(44):
                    if cip[i].isupper() or cip[i].islower():
                        keylis[i] = (ord(cip[i]) - ord(msg[i])) % 26

print(keylis)
result = ""
for i in range(44):
    if flag_cip[i].isupper():
        result += chr((ord(flag_cip[i]) - ord('A') - keylis[i]) % 26 + ord('A'))
    elif flag_cip[i].islower():
        result += chr((ord(flag_cip[i]) - ord('a') - keylis[i]) % 26 + ord('a'))
    else:
        result += flag_cip[i]
print(result)

Dancing Line

给了一张图片

图片

转向处当1不转当0,左上走到右下,碰见黑的就截断,ascii就是flag

类似摩斯,只不过是图片形式。可以自己记录下转向与否再解密,或者直接写个脚本,这里用的其他师傅的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image
import numpy as np
ppp = Image.open('Dancing Line.bmp')
mmm = np.asarray(ppp)
m = mmm.shape[0]
n = mmm.shape[1]
pos = []
for i in range(m):
    for j in range(n):
        if mmm[i][j][0] != 255:
            pos.append((i, j))
typ = 1
liss = []
tmp = 0
for i in range(1, len(pos)):
    tmp_typ = (pos[i - 1][0] == pos[i][0])
    tmp = 2 * tmp + (typ ^ tmp_typ)
    if i % 8 == 0:
        liss.append(tmp)
        tmp = 0
for x in liss:
    print(chr(x), end = '')

IOT

饭卡的uno

图片

直接把附件扔进ida,加个H就是flag

接上文

PWN

test_your_nc

nc一下,直接ls就是flag

WEB

蜘蛛

每个网页都有进入下一关的url,大概到了100关找一下flag,写一个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
from bs4 import BeautifulSoup

payload='?key=waIhAPv5m%2FNnK8InBODSntbsBfxO0q5vPSQsMdFbo6lmSt1UNIAAAhoj%2FNP38yVBeU%2BUYKJQOG0k0HMjfeihTA%3D%3D'
def html(payload):
    url='https://hgame-spider.vidar.club/450bc23c34'
    html_text=requests.get(url=url+payload).text
    soup = BeautifulSoup(html_text,'lxml')
    tag=soup.find_all('a')
    for i in tag:
        if i.attrs['href'] != '':
            real_payload=i.attrs['href']
            print('[*]'+real_payload)
            html(real_payload)
html(payload)

Tetris plus

翻看js文件

图片

发现jsfuck

放到控制台运行

图片

Fujiwara Tofu Shop

一步一步按照提示构造数据包就行,主要考察http的知识

1
2
3
4
5
6
7
8
GET / HTTP/1.1
Host: shop.summ3r.top
User-Agent: Hachi-Roku
referer:qiumingshan.net
Cookie: flavor=Raspberry
gasoline:100
x-real-ip:127.0.0.1
Connection: close

easy_auth

http://adminisdoingwhat.mjclouds.com/

先注册一个账号

admin admin

然后登录查看返回包

图片

发现token为jwt

放到https://jwt.io/#debugger-io解密

发现有密钥 爆破一下

发现为空

图片

修改字段进行加密

图片

发现泄露app.js

进行查看

关键位置代码

图片

图片

访问http://whatadminisdoingwhat.mjclouds.com/v1/todo/list

带上我们之前的加密出来的token发送

图片

A+B这种题目,这道题目就是让我们输出 A + B 的值,但是这道题目呢?大整数加法同样是计算两个数的和,但是这两种题目的解法是完全不同的。如果我们还像之前一样这样写那么题目肯定会 WA 

1
2
3
4
5
6
7
8
9
#include<iostream>
using namespace std;

int main() {
    int A, B;
    cin >> A >> B;
    cout << A + B << endl;
    return 0;
}

因为后者的数据范围大大超过了int以及double等数据类型,会导致数据溢出,为了解决这种问题,就需要采用了高精度算法。

高精度算法简介

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。

在C/C++的计算中如果处理不好很容易出现数据溢出的情况。比如 int 型数据的范围为 -2147483648 ~ +2147483647 (4 Bytes)如果一个比这个数据范围还要大的数,那么我们就不能直接存储在 int 变量中,否则会出现数据溢出的问题。一般我们做题目的时候题目都会提供数据范围,当给定的数据范围很大的时候我们一定要注意这个题目是不是高精度问题。

大数的存储方式

对于数字习惯先写高位再写低位,但是在计算机中计算的时候如果我们也按照从高位到低位存储数字,对我们写程序造成了不必要的麻烦。所以在数组中我们按照从低位到高位存储大数,即先存个位,再存十位,再存百位……。比如我们有一个数组 A ,那么A[0]存个位,A[1]存十位,A[2]存百位……以此类推。

 由于高精度数都比较大,所以在存储的过程中我们一般先以将数字存到一个 string 类型的字符串中,然后将其每一位减去 ‘0’ 再存入到数组中(因为在计算机中每一个字符都有它的ASCII码,字符’0’ - ‘9’ 的 ASCII码的范围为 48 - 57,用字符串中每一个字符的ASCII码减去 ‘0’ 的ASCII码正好对应相应的数字)。

图片

高精度加法详解

 其实高精度加法并没有我们想象中的那么难,实现的过程就是模拟了我们笔算加法的过程。首先从个位开始相加,先将两个数组的第一位A[0]、B[0]相加即两个数的个位相加。使用一个变量 t 来存储相加的结果,将想相加之后的结果对 10 取模然后存到结果数组的个位上即C[0]上。然后再使 t 除以 10 如果两个个位相加超过了 10 那么除以 10 之后的到的就是进位的结果,然后依次相加十位百位等等,直到两个数组的数字都加完。这里我们需要设置一个 变量 i = 0 来记录遍历数组的下标,如果 i 还没有超过数组最大的下标那么就相加,否则就不想加。

 比如 1234 + 56 我们会将其存储为 4321 + 65,4 + 6 = 10 ,10 % 10 = 0,10 / 10 = 1,所以我们将 0 存储在C[0]上,t = 1,然后再将 t + 3 = 4 , t + 5 = 9,此时9 % 10 = 9,9 / 10 = 0 , t = 0,这时56已经加完了,所以我们直接计算 t + 2 = 2, t = 0,t + 1 = 1,t = 0。所以最终 C[0] = 0,C[1] = 9,C[2] = 2,C[3] = 1,倒着输出数组C中的数字,即 1290 就是我们的答案了。

 这里要特别注意:我们在 for 循环的结束条件还需要判断一下 t 是否为 0 因为即使最后将两个数加完了还可能存在进位的可能,如果不加这个条件那么最高位就会少个 1。

大整数加法题目详解

题目描述

 求两个不超过 200200 位的非负整数的和。

输入格式

 有两行,每行是一个不超过 200200 位的非负整数,可能有多余的前导 00。

输出格式

 一行,即相加后的结果。结果里不能有多余的前导 00,即如果结果是 342342,那么就不能输出为 03420342。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

22222222222222222222

33333333333333333333

样例输出

55555555555555555555

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<stdio.h>
#include<string.h>
#define max 300
int main()
{
    char a[max] = {0},b[max] = {0};
    int a1[max] = {0},b1[max] = {0},c1[max] ={0};
    int a_len,b_len,i;
    scanf("%s",&a);
    scanf("%s",&b);
    a_len = strlen(a);
    b_len = strlen(b);
    for(i = 0;i < a_len;i++)
        a1[i] = a[a_len - i - 1] - '0';
    for(i = 0;i < b_len;i++)
        b1[i] = b[b_len - i - 1] - '0';
    int t = 0,x = 0;
    while(t < a_len || t < b_len)
    {
        c1[t] = a1[t] - b1[t] + x;
        x = c1[t] / 10 ;
        c1[t] %= 10;
        t++;
    }
    while(!c1[t] && t)
    {
        t--;
    }
    for(;t >= 0;t--)
        printf("%d",c1[t]);
    return 0;
}

高精度减法详解

大整数减法又叫高精度减法,对于该问题首先我们要考虑如何在计算机中存储大整数

判断两个数的大小

做大整数减法首先我们需要判断一下 减数 和 被减数 哪一个更大。比如大整数 a - b,如果 a > b,那么结果为正数,在输出时我们就不用考虑输出负号;如果 a < b,那么结果为负数,我们需要将 a - b 改为 - (b - a) 来计算,我们只需要计算 b - a,最后在输出时先输出一个负号即可。因为在该题题目中保证了 被减数 a 大于减数 b (a>b) 所以我们就可以省略这一步直接进行相减即可

大整数减法实现

定义一个变量 int t = 0 作为借位的标记。因为在主函数传参时我们保证了 a 一定是大于 b 的,所以我们循环遍历 a,从个位开始逐位相减。这里的 t 是实现大整数减法的关键,首先我们计算一下当前位的值为多少比如我们开始计算两个数的个位相减,我们使用之前定义的变量 t 来存储结果,即 t = A[0] - B[0] - t,这里后面的 t 即为借位,如果 t 的结果大于 等于0 ,说明在两个数的个位 A[0] >= B[0] 那么就不需要借位那么我们将 t 设置为 0 下一次计算十位的时候依旧是 t = A[1] - B[1] - t ,之后我们将这个结果存储在C[0]上,即结果的个位。如果 t 的结果小于 0 ,那么说明需要借位,那么我们就将结果 +10 。然后将 t 设置为 1,证明我们借位了,在下一次t = A[1] - B[1] - t 时需要多减去一个 1。这里还要注意在相减的过程中我们要判断一下B的该位是否存在,存在我们才相减,不存在就不进行相减,所以在我们分开来算t = A[1] - B[1] - t

题目详解

求两个大的正整数相减的差。

输入格式

 共 2 行,第 1 行是被减数 a,第 2 行是减数 b(a > b)。每个大整数不超过 200 位,不会有多余的前导零。

输出格式

一行,即所求的差。

输出时每行末尾的多余空格,不影响答案正确性

样例输入

9999999999999999999999999999999999999

9999999999999

样例输出

9999999999999999999999990000000000000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <string.h>
int main() {
char a[202] = {0}, b[202] = {0};//输入
int a1[202] = {0}, b1[202] = {0};//计算
int a_len, b_len, t = 0, i;
scanf("%s%s", a, b);
a_len = strlen(a);
b_len = strlen(b);

for (i = 0; i < a_len; i++)
a1[i] = a[a_len - 1 - i] - '0';
for (i = 0; i < b_len; i++)
b1[i] = b[b_len - 1 - i] - '0';



a_len = (a_len > b_len) ? a_len : b_len;//找两个数里面长的
for (i = 0; i <= a_len; i++) {//正常的进位算法
t = a1[i] - b1[i];
if (t<0){
t+=10;
a1[i+1]--;
}
a1[i] = t;

}
while (!a1[i] && i)//找起始位(避坑n+0)
i--;
for (; i >= 0; i--)
printf("%d", a1[i]);
return 0;
}

高精度乘法详解

 高精度算法简介已经在上文中详细的介绍过了,这里就不再赘述了

大数的存储方式

 大数的存储方式也在上文中详细的介绍过了,这里也不再赘述了。这里主要介绍一下高精度乘法的实现方式。

精度乘法实现

 这里主要介绍一下一个大整数 A 乘以一个比较小的数 b 的实现方法,两个大整数相乘的实现方法是一样的,不同之处在于两个大数相乘需要将第二个数也拆开分别进行相乘。首先我们定义一个vector数组 ans 来存储相乘之后的结果,定义一个整型变量 t 来存储每次的进位的值。因为是倒着存储的大数,所以在相乘的时候我们从下标为 0 的数字开始相乘依次向后遍历,并且将每次的相应数位相乘的结果放到数组 ans 中。

 每次相乘之前我们都需要先判断一下数组是否越界了,如果没有越界就使 t 加上当前位乘以较小的数字 b(注意:因为第二个数字 b 比较小,所以我们直接使 A[i] * b,即大数 A 的每一位数字 直接与 b 相乘,而不需要将 b 拆开,因为 b 比较小,所以我们不需要像大数 A 那样将 A 的每一位拆开进行相乘。 )。然后将 t % 10 即结果的个位放在当前位置上,然后使 t /= 10 算出进位的值,在下一次循环直接加上该进位的值即可。重复进行这一操作直到将数组 A 中的所有数位乘完,并且检查一下 t 是否进完位,如果相乘结束之后 t 不为 0 ,说明最后一个数位与 b 相乘还是需要进位,那么就继续执行 t % 10,t /= 10 的操作,直到 t = 0为止。

题目详解

题目描述

 任意给定一个正整数 N (N≤100),计算 2 的 N 次方的值。

输入格式

 输入一个正整数 N。

提示

高精度计算。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

5

样例输入

5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<stdio.h>
#include<string.h>
void timesTwo(char ans[])
{
    int len = strlen(ans);
    int tmp[1005] = {0};
    int sum[1005] = {0};
    for(int i = 0;i < len;i++)
        tmp[i] = ans[len - i - 1] -'0';
    for(int i = 0;i < len;i++)
    {
        sum[i] += tmp[i] * 2;
        sum[i + 1] += (sum[i] / 10);
        sum[i] %= 10;
    }
    int flag = 0;
    for(int i = len,j = 0;i >= 0;i--)
    {
        if(sum[i] != 0 || i == 0)
        {
            flag = 1;
        }
        if(flag)
        {
            ans[j++] = sum[i] + '0';
        }
    }
}
int main()
{
    char ans[1005] = {'1'};
    int n;
    scanf("%d",&n);
    for(int i = 0;i < n;i++)
    {
        timesTwo(ans);
    }
    printf("%s",ans);
    return 0;
}

高精度除法详解

高精度算法简介

 高精度算法简介已经在上文中详细的介绍过了,这里就不再赘述了

大数的存储方式

大数的存储方式也在上文,这里也不再赘述了。但是我们要注意的是在除法的过程中我们是从最高位开始计算的,而不是像加减乘法一样从最低位开始计算,但是我们在除法的大整数存储中依旧是按照先存最低位再存高位。因为往往在一个高精度问题中不单单会涉及到除法,可能还会有加减乘法运算,所以为了方便我们在存储大整数的时候都是按照由低位到高位存储,即倒着存储。下面来详细的介绍一下如何实现大整数除法。

高精度除法实现

首先我们想一下我们在笔算除法的时候的计算步骤,在大整数 A1A2A3A4A5A6 ÷ b 先判断一下最高位的数字A1能不能除开 b,除不开就落下来然后再计算A1A2 是否能够除开 b;如果能够除开那么就将商写在上面然后求出余数 r ;再计算下一位,将余数 r * 10 + A3,然后再计算商余数知道将所有的数位都除完,最后就剩下了最终的商和余数。

计算机中的大整数除法和我们笔算的时候思路是一样的,首先我们定义一个余数 r = 0,先使 r = r * 10 + A1,然后计算 r / b 的结果,然后使 r %= b,求出当前的余数再进行下一位的运算即使 r = r * 10 + A2,将 r / 10 ,然后再计算余数 r %= b;一直循环往复下去直到算完所有的数位。

题目详解

题目描述

 已知正整数 k 满足 2 ≤ k ≤ 9,现给出长度最大为 30 位的十进制非负整数 c,求所有能整除 c 的 k。

输入格式

 一个非负整数 c,c 的位数 ≤ 30。

输出格式

若存在满足 c % k = 0 的 k,从小到大输出所有这样的 k,相邻两个数之间用单个空格隔开;若没有这样的 k,则输出”none”。

 输出时每行末尾的多余空格,不影响答案正确性

样例输入

30

样例输出

2 3 5 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<stdio.h>
#include<string.h>
int numMod(char s[],int k)
{
    int c[35] = {0};
    int len = strlen(s);
    for(int i = 0;i < len;i++)
        c[i] = s[i] - '0';
    int res = 0;
    int newNum = 0;
    for(int i = 0;i < len;i++)
    {
        newNum = res * 10 + c[i];
        res = newNum % k;
    }
    return res;
}
int main()
{
    char C[35] = {0};
    int flag = 0;
    scanf("%s",C);
    for(int k = 2;k <= 9;k++)
    {
        if(numMod(C,k) == 0)
        {
            flag = 1;
            printf("%d ",k);
        }
    }
    if(!flag)
    {
        printf("none");
    }
    return 0;
}

高精度阶乘例题

题目描述

求10000以内n的阶乘。

输入格式

只有一行输入,整数n(0≤n≤10000)

输出格式

一行,即n!的值。

样例输入

4

样例输出

24

分析

首先n的阶乘是从1开始相乘,乘到n为止的总乘积。定义很简单,但是要注意下数据范围,本题的n最大到达了10000。而13的阶乘就已经解决int范围的极限了,更别提10000了。这道题的答案很大,所以要用大数的方式来进行处理。

另外,n!=(n−1)!×n

n!=(n−1)!×n而n的范围又在10000以内,所以可以看作是一个大数乘一个int范围内数字的问题,就不用使用高精乘高精的方法了。

乘法计算时也是类似竖式计算的过程。将小的数字i与大数的每一位相乘,且从低位开始相乘。过程中进行进位操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<stdio.h>
int ans[100005]={1,1};//存放阶乘 ans[0]是位数 倒序存放数字 
int jw[100005];//进位的值 
int n;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){//遍历1~n
//求出i的阶乘
// i!= (i-1)! * i 
for(int j=1;j<=ans[0];j++){
//ans[0]中存放阶乘的位数   
ans[j]=ans[j]*i+jw[j];//将i与每一位进行相乘 
jw[j]=0;//重置进位值 

if(ans[j]>=10){//超过10要进位 
jw[j+1]+=ans[j]/10;//记录进位值 
ans[j]%=10;//保留个位 

if(j==ans[0]) ans[0]++;//如果到了位数又发生进位,那么位数要发生变化 
}
}
}

for(int i=ans[0];i>=1;i--){//从高位开始倒序输出结果 
printf("%d",ans[i]);
}
return 0;
}

其实很简单,但是不知道为啥卡了我思维半天,想通了就豁然开朗(状态不太行

小蒜想让你根据参数,画出一个他想要的矩形。

输入格式

输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于 3

3 行不多于 10

10 行,宽不少于 5

5 列不多于 10

10 列);第三个参数是一个字符,表示用来画图的矩形符号;第四个参数为 1

1 或 0

0,0

0 代表空心,1

1 代表实心。

输出格式

输出画出的图形。

小蒜想让你根据参数,画出一个他想要的矩形。

样例输入

1
7 7 @ 0

样例输出

1
2
3
4
5
6
7
@@@@@@@
@ @
@ @
@ @
@ @
@ @
@@@@@@@

【解题思路】

思路1:按行输出

输入高h,宽w,字符c,是否实心x

内部字符c_in有两种,若是实心图形,内部字符是c,若是空心图形,内部字符是’ ‘(空格)

上下两行,需要输出w个c,再输出换行。

中间的h - 2行,需要先输出一个c,再输出w - 2个c_in,再输出一个c,再输出换行。

思路2:遍历矩阵

循环嵌套输出整个矩阵

针对每个位置进行判断,如果符合条件,则输出*,否则输出’ ‘。

条件为:

如果是外圈,即行号为1或h,或列号为1或w,那么输出*

如果不是外圈,是内部位置,那么判断是否是实心,是实心输出*,否则输出’ ’

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
int main()
{
    int h,w,x;
    char  c;
    scanf("%d %d %c %d",&h,&w,&c,&x);
    char c_in = x == 1 ? c : ' ';
   for(int i = 0;i < w;i++)
        printf("%c",c);
    printf("\n");
    for(int i = 0;i < h - 2;i++)
    {
    printf("%c",c);
    for(int j = 0;j < w - 2;j++)
        printf("%c",c_in);
    printf("%c\n",c);
    }
    for(int i = 0;i < w;i++)
    {
        printf("%c",c);
    }
    printf("\n");
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2.#include<stdio.h>
int main()
{
    int h,w,x;
    char c;
    scanf("%d %d %c %d",&h,&w,&c,&x);
    for(int i = 1;i <= h;i++)
    {
        for(int j = 1;j <= w;j++)
        {
            if(i == 1 || i == h || j == 1 || j == w)
                printf("%c",c);
            else
            {
                if( x == 1)
                    printf("%c",c);
                else
                    printf(" ");
            }
        }
        printf("\n");
    }
    return 0;
}

【题目描述】

蒜头君有一个正整数 n,他想求第 n小的质数。

【输入格式】

一个不超过 10000的正整数 n。

【输出格式】

第 n 小的质数。

输出时每行末尾的多余空格,不影响答案正确性

【样例输入】

1
10

【样例输出】

1
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<stdio.h>
#include<math.h>
int isprime(int m) { //判断一个数是不是质数 
    int i;
    for(i=2; i<=sqrt(m); i++) 
        if(m%i==0)
                return 0;
    return 1;
}
int main() 
{
    int n,sum=0;//定义第n小,质数累加 
    scanf("%d",&n); 
    for(int i=2;;i++)
    {
        if( isprime(i)==1)
            sum++;
        if(sum==n)  //等于第n小的时候输出 
        {
            printf("%d\n",i); 
            break;
        }       
    }
    return 0;
}

一、常用Window+R键命令

cmd         //命令窗口

mspaint     //打开画板

calc        //打开计算器

msconfig    //打开系统启动配置窗口

services.msc//启动本地服务操作窗口

control     //打开控制面板

notepad     //打开记事本

regedit     //注册表

二、常用CMD命令

shutdown -s -t 30    //30秒后关机

d:                   //切换盘符

dir                  // 查看当前路径内的内容

cd d:/test           //绝对路径,从盘符开始的路径

cd ./test            //相对路径,从当前目录开始(.为当前路径,..为上一级目录)

cd \                 //直接退回到盘符 

cls                  //清屏

exit                 //退出CMD窗口   

md 名称              //创建文件夹

rename 旧名 新名     //重命名文件夹

xcopy 源文件夹 目的文件夹  /s/d/e   

 //复制文件(夹)  /s复制文件夹下所有子文件夹和文件  /e即使有空文件夹也会复制   /d复制过程显示

rd 文件夹  /s       //删除文件(夹)/s删除文件夹下所有子文件夹和文件

type nul>文件名     //创建空文件

echo a>文件名       //创建指定内容的文件

rename 旧名 新名    //重命名文件

copy 源路径 目的路径   //路径要么都是相对路径,要么都是绝对路径

del 文件名          //删除文件   (如del *.txt 会删除所有扩展名为txt的文件)

ipconfig   //查看网卡信息

、环境变量:

1.定义:

例如Windows操作系统中的path环境变量,当要求系统运行一一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到path中指定的路径去找。用户通过设置环境变量来更好的运行进程。

即如果想让一个程序不管是在哪一个目录下都能运行,就需要配置一个环境变量。

2.配置方法:

我的电脑右键属性->高级系统设置->高级->环境变量->系统变量->path双击->新建->输入路径->确定

但是这样有一个缺陷,即如果在一个目录下存在多层嵌套的子目录中有很多的路径需要设置,必须每一个路径都分别配置,这样会显得路径特别长。因此可以直接设置一个系统变量来解决,即将一部分相同的路径作为一个变量名使用。

1.我的电脑右键属性->高级系统设置->高级->环境变量->系统变量->新建->输入变量名(例如:Text),变量值(即路径,不要用中文的字符)->确定

2.path双击->新建->%Text%\hello\1->确定(用%%把变量名括起来,如果是变量名对应变量值的子目录,那么在后面跟上相应的路径)

3.(代替2的操作,是俩种编辑方式,看打开以后出现的是啥来判断)可以直接在path的变量值后面以‘;’分割,添加想要添加的路径名

3.注意事项:

路径必须是.bat文件所在目录的的绝对路径

在path中将路径上移或下移可以改变环境变量搜索顺序,提高搜索效率。

都是普及T1题,有点复杂,但代码不多,较绕,体会到算法选手的天赋所在了(我爬了)

39:与7无关的数

总时间限制:  1000ms  内存限制:  65536kB

描述

一个正整数,如果它能被7整除,或者它的十进制表示法中某一位上的数字为7,则称其为与7相关的数.现求所有小于等于n(n < 100)的与7无关的正整数的平方和.

输入

输入为一行,正整数n(n < 100)

输出

输出一行,包含一个整数,即小于等于n的所有与7无关的正整数的平方和。

样例输入

21

样例输出

2336

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
源码

#include<stdio.h>
int main()
{
    int n,sum = 0,flag;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
    {
        flag = 0;
        if(i % 7 == 0 || i % 10 == 7 || i / 10 == 7)
            flag = 1;
        if(!flag)
            sum += i * i;
    }
    printf("%d",sum);
    return 0;
}

79:开关灯

假设有 N 盏灯(N 为不大于 5000 的正整数),从 1 到 N 按顺序依次编号,初始时全部处于开启状态;有 M 个人(M 为不大于 N 的正整数)也从 1 到 M 依次编号。

第一个人(1号)将灯全部关闭,第二个人(2号)将编号为 2 的倍数的灯打开,第三个人(3 号)将编号为 3 的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和 3 号一样,将凡是自己编号倍数的灯做相反处理。

请问:当第 M 个人操作之后,哪几盏灯是关闭的,按从小到大输出其编号,其间用逗号间隔。

输入格式

输入正整数 N 和 M,以单个空格隔开,M<=N。

输出格式

顺次输出关闭的灯的编号,其间用逗号间隔。

注:输出时每行末尾的多余空格,不影响答案正确性

样例输入

10 10

样例输出

1,4,9

题目分析:

M个人中一号人的唯一作用是把灯全部关闭,因此直接从二号开始思考;

这个题里面只有开关两种状态,在1号的作用下灯都关着,因此初状态全部为0;

把初状态数组规定成{0},最后是0的都是被灭掉的

在每一个符合条件的人碰一次灯时,灯的状态改变一次

而此条件是人组成的数组中每个人自身编号的倍数,因此只需在人的数组循环中再嵌套一个倍数

循环进行乘积。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h>
#include<math.h>
int main()
{
int i,j,k,a[5000]={0},b[5000]={0},n;//a[i]这个数组为每个人附上编号
int N,M;                            //b[i]则是灯的逻辑数组
scanf("%d %d",&N,&M);
for(i=2;i<=M;i++)//给人编号
{
        a[1]=1;
a[i]=a[i-1]+1;
        for(n=1;a[i]*n<=N;n++)//a[i]*n是每个人对应编号的倍数,即所需改变的灯的序号
        {
            j=a[i]*n;
            b[j]=!b[j];
        }
}
for(k=1;k<=N;k++)//找出还灭着的项,输出
{
if(b[k]==0)
        {
            if(k==1) 
            printf("1");//这块让结尾不出现逗号,虽然不知道最后一项筛选的是哪个数
            else 
            printf(",%d",k);//但是第一项一定是1,所以先输出逗号
        }
}
    return 0;
}

84:雇佣兵

描述

雇佣兵的体力最大值为M,初始体力值为0、战斗力为N、拥有X个能量元素。

当雇佣兵的体力值恰好为M时,才可以参加一个为期M天的战斗期,战斗期结束体力值将为0。在同一个战斗期内,雇佣兵每连续战斗n天,战斗力就会上升1点,n为当前战斗期开始时的战斗力。

一个战斗期结束后,雇佣兵需要用若干个能量元素使其体力恢复到最大值M,从而参加下一个战斗期。每个能量元素恢复的体力值不超过当前的战斗力。每个能量元素只能使用一次。

请问:雇佣兵的战斗力最大可以到达多少。

输入

一行包括三个整数M、N、X,相邻两个整数之间用单个空格隔开。M、N、X均为不超过10000的正整数。

输出

输出一个整数,为雇佣兵的最大战斗力。

样例输入

1
5 2 10

样例输出
6

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//c语言版
#include <stdio.h>

int main()
{
int m,n,x;
scanf("%d%d%d",&m,&n,&x);
int M = 0;//初始体力值为0 
for(int i=0;i<x;i++){//能量元素 恢复体力 
M += n;//用能量元素恢复体力 
if(M>=m){//恢复完毕 
n+=m/n;/*雇佣兵每连续战斗n天,战斗力就会上升1点
这里战斗天数为m*/ 
M=0;//结束后体力为0 
}
}
printf("%d",n);
}

其实雇佣兵这道题挺绕,但理解了代码反而不是很难,这种拿给我这种没基础的,简直要命(想半天),网上找了个思路解析,附上。

一,流程图

图片

二,提取关键点

1.不知道每个能量元素具体回复多少体力

2.雇佣兵初始体力值为0

3.雇佣兵通过战斗期来提升战斗力

4.当雇佣兵的体力值恰好为体力最大值时,才可以参加战斗期

三,解决关键点

1.不知道每个能量元素具体回复多少体力

因为求的是最大战斗力的情况,所以为了物尽其用,每个能量元素能回复的体力等于当前的战斗力。

2.雇佣兵初始体力值为0

在循环前就使用一次能量元素将体力恢复到最大值。

3.雇佣兵通过战斗期来提升战斗力

通过循环模拟战斗期,每次循环增加当前状况最多能增加的战斗力。

4.当雇佣兵的体力值恰好为体力最大值时,才可以参加战斗期

每次循环结束,使用一次能量元素将体力恢复到最大值。

如果能量元素不能将体力恢复到最大值,则跳出战斗期,并输出目前的战斗力。

=====注意=====

每次使用能量元素,需要将当前所拥有的能量元素数量减去使用的能量元素数量

前言:报了个蓝桥B,想混个奖给期末加个分,临时学下算法,先从基础开始吧

0001 . 计算A+B(c语言入门练习题)

打开新世界的大门,从通过这道题开始!ヽ(●´∀`●)ノ

输入两个整数 A,B 计算 A+B的结果

你需要写一个程序,实现从标准输入中输入两个整数 A和 B,然后把 A+B 的结果输出到标准输出。

比如 C 语言中的标准输入输出为方法为scanf和printf,C++ 中标准输入输出的方法为cin和cout。

注意:不要输出任何多余的辅助信息。

1
2
3
4
5
6
7
#include <stdio.h>
int main (void){
int a , b ;
scanf("%d %d",&a,&b);
printf("%d",a+b);
return 0;
}

0002 . 输出马里奥(c语言入门练习题)

超级玛丽是一款深受大家欢迎的游戏(๑ơ ₃ ơ)♥

  • 现在让我们以字符画的形式输出一个管道工人马里奥吧~
    输入格式 

输出格式 如样例所示



   ####….#.

 #..###…..##….

 ###…….######

    ………..

   ##*#######

 ####*******######

…#..###….

….**********##…..

….****    *****….

  ####        ####

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 #include <stdio.h>
 int main (void){
        
    printf("        ********          \n");
    printf("       ************       \n");
    printf("       ####....#.         \n");
    printf("     #..###.....##....     \n");
    printf("     ###.......######     \n");
    printf("        ...........       \n"); 
    printf("       ##*#######         \n");
    printf("    ####*******######     \n");
    printf("   ...#***.****.*###....  \n");
    printf("   ....**********##.....  \n");
    printf("   ....****    *****....  \n");
    printf("     ####        ####     \n");
    printf("   ######        ######   \n");
           
    return 0;
}

0003 . 输出字符菱形(c语言入门练习题)

小蒜蒜最近学习了菱形(四边都相等的四边形)。

  • 现在她给了你一个字符,希望你能用它构造一个对角线长 5 个字符,倾斜放置的菱形。
    输入格式输入只有一行,包含一个字符

输出格式该 字符 构成的 菱形

样例输入 *

样例输出

    *




    *

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
int main (void){
    int a = 1;
    int c = 1;
    char b;
    scanf("%c",&b);
    for(a=1;a<=3;a++){
        for(c=1;c<=3-a;c++){
            printf(" ");
        }
        for(c=1;c<2*a;c++){
            printf("%c",b);
        }
        printf("\n");
    }
    for(a=1;a<=2;a++){
        for(c=1;c<a+1;c++){
            printf(" ");
        }
        for(c=5;c>2*a;c--){
            printf("%c",b);
        }
        printf("\n");
    }
    
    return 0;
}

0004 . 输出Hello, World!(c语言入门练习题)

对于大部分编程语言来说,编写一个能够输出 “Hello, World!” 的程序往往是最基本、最简单的。

因此,这个程序常常作为一个初学者接触一门新的编程语言所写的 第一个程序,也经常用来测试开发、编译环境是否能够正常工作。

蒜厂也为大家准备了这么一道题,现在你就可以通过写一个输出 “Hello, World!” 的程序来通过这道题啦~

输入格式 无。

输出格式一行,仅包含一个字符串:“Hello, World!”

代码:

1
2
3
4
5
6
7
8
#include <stdio.h>

int main (void){
    
    printf("Hello, World!");
    
    return 0;
}

0005 . 输出字符三角形(c语言入门练习题)

小蒜蒜又想让你输出一个新的形状了。

  • 现在给定一个字符,希望你用它构造一个底边长 5 个字符,高 3 个字符的等腰字符三角形。
  • 输入格式*

输入只有一行,包含一个字符

输出格式

该字符构成的等腰三角形,底边长 5 个字符,高 3 个字符

代码:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main (void){
    
    char a;
    
    scanf("%c",&a);
    
    printf("  %c  \n %c%c%c \n%c%c%c%c%c\n",a,a,a,a,a,a,a,a,a);
  
    return 0;
}

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main (void){ 
    char a ;
    int i ,j ;
    scanf("%c",&a);
    for(i=1;i<=3;i++){
        for(j=1;j<=3-i;j++){
            printf(" ");
        }
        for(j=1;j<i*2;j++){
            printf("%c",a);
        }
        printf("\n");
    }
    return 0;
}

0006 . 对齐输出(c语言入门练习题)

为了能够更清晰整齐地看到输出结果,我们可以去控制输出的格式

  • 读入三个整数,按每个整数占 8 个字符的宽度,右对齐输出它们。
  • 输入格式*

只有一行,包含三个int范围内整数,整数之间以一个空格分开。

输出格式

只有一行,按照格式要求依次输出三个整数,之间以一个空格分开

代码:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main (void){
    
    int a , b ,c ;
    
    scanf("%d%d%d",&a,&b,&c);
    
    printf("%8d %8d %8d",a,b,c);
    
    return 0;
}

0007 . 整型与布尔型的转换(c语言入门练习题)

  • 将一个整型变量的值赋给一个布尔型变量,再将这个布尔型变量的值赋给一个整型变量,得到的值是多少?
  • 快来试试会发生什么!*

输入格式

一个整型范围内的整数,即初始时整型变量的值。

输出格式

一个整数,经过上述过程后得到的结果

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main (void){
    
    _Bool B ;
    int num , num1 ;
    
    scanf("%d",&num);
    
    B = num ;
    num1 = B ;
    
    printf("%d",num1);
    
    return 0;
}

0008 . 打印字符(c语言入门练习题)

蒜头君知道每个字符都有一个对应的 ASCII 码。

  • 现在输入一个 ASCII 码,要求你输出对应的字符。
  • 输入格式*

一个整数,即字符的 ASCII 码,保证对应的字符为可见字符。

输出格式

一行,包含相应的字符。

代码如下 :

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main (void){
    
    int num;
    
    scanf("%d",&num);
    
    printf("%c",num);
    
    return 0;
}

0009 . 等差数列末项计算(c语言入门练习题)

等差数列是一个很有趣的数列,它的任何相邻两项的差相等。

蒜头君给出一个等差数列的前两项 a1,a2,求第 n 项是多少。

输入格式

一行,包含三个整数 a1 , a2 , n 。−100 ≤ a1 , a2 ≤ 100 , 0 < n ≤ 1000 。

输出格式

一个整数,即第 n 项的值。

代码如下 :

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main (void){
    int s1 , s2 , n , s;
    
    scanf("%d%d%d",&s1,&s2,&n);
    
    s=s1+(s2-s1)*(n-1);
    printf("%d",s);
    
    return 0;
}

0010 . 计算线段长度(c语言入门练习题)

已知线段的两个端点的坐标 A(Xa,Ya),B(Xb,Yb),求线段 AB 的长度。蒜头君老师告诉了你计算公式如下图片

输入格式

共两行 :
第一行是两个实数 Xa,Ya,即 A 的坐标。
第二行是两个实数 Xb,Yb,即 B 的坐标。
输入中所有实数的绝对值均 不超过 10000
输出格式

一个实数,即线段 AB 的长度,保留到小数点后 3 位。
代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>

int main(void){
     double a1,a2,b1,b2;
     double z;
 
     scanf("%lf%lf",&a1,&a2);
     scanf("%lf%lf",&b1,&b2);
 
     z=sqrt( (a1-b1)*(a1-b1) + (a2-b2)*(a2-b2) );
 
     printf("%.3f", z);
 
     return 0;
}

0011 . 反向输出一个三位数(c语言入门练习题)

  • 小蒜蒜有一个三位数,她想让聪明的你反向输出这个三位数。
  • 输入格式*

一个三位数 n (100≤n≤999)。
输出格式

反向输出 n,要保留前导 0。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main (void){
    int num;
    int g ,s ,b;  //个位 十位 百位
    
    scanf("%d",&num);
    
    b=num/100;   
    s=(num/10)%10;
    g=num%10;
    
    printf("%03d",g*100+s*10+b);
    
    return 0;
}

0012 . A*B问题(c语言入门练习题)

相信你已经学会 A+B 问题了,那么问题又来了~

  • 输入两个正整数 A和 B ,求 A×B。
  • 输入格式*

一行,包含两个正整数 A 和 B,中间用单个空格隔开。1≤A,B≤50000。
输出格式

一个整数,即 A×B 的值。
代码如下 :

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main (void){
    long a,b;     //int 无法表达 50000*50000 的数字
    
    scanf("%ld%ld",&a,&b);
  
    printf("%ld",a*b);
  
    return 0;
}

0013 . 输入第二个整数(c语言入门练习题)

小蒜蒜有一个简单的问题给你,相信你一定可以搞定的!

输入三个整数,把第二个输入的整数输出。

输入格式

只有一行,共三个整数,整数之间由一个空格分隔。整数是 32

32 位有符号整数。

输出格式

只有一行,一个整数,即输入的第二个整数。

输出时每行末尾的多余空格,不影响答案正确性

样例输入

复制

1
123 456 789

样例输出
复制

1
456
1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
printf("%d",b);
return 0;
}

0014 . 输出保留3位小数的浮点数(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9

#include<stdio.h>
int main()
{
    double a;
    scanf("%lf",&a);
    printf("%.3f",a);
    return 0;
}

0015 . 输出保留12位小数的浮点数(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
    double a;
    scanf("%lf",&a);
    printf("%.12f",a);
    return 0;
}

0016 . 打印ASCII码(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
char a;
scanf("%c",&a);
printf("%d",a);
    return 0;
}

0017 . 计算(a+b)*c的值(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
printf("%d",(a+b)*c);
return 0;
}

0018 . 计算(a+b)/c的值(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
    int a,b,c;
    scanf("%d %d %d",&a,&b,&c);
    printf("%d",(a+b)/c);
    return 0;
}

0019 . 带余除法(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
    int a,b;
    scanf("%d %d",&a,&b);
    printf("%d %d",a/b,a%b);
    return 0;
}

0020 . 计算分数的浮点数值(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
#include<stdio.h>
int main()
{
    double a,b;
    scanf("%lf %lf",&a,&b);
    printf("%.9f",a/b);
    return 0;
}

0021 .  甲流疫情死亡率c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
    double a,b,c;
    scanf("%lf %lf",&a,&b);
    c = b * 100 / a;
    printf("%.3f%%",c);
    return 0;
}

0022 .  计算多项式的值(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main()
{
    double a,x,b,c,d,f;
    scanf("%lf %lf %lf %lf %lf",&x,&a,&b,&c,&d);
    f = a * x * x * x + b * x * x + c * x + d;
    printf("%.7f",f);
    return 0;
}

0023 .  温度表达转化(c语言入门练习题)

图片

1
2
3
4
5
6
7
#include<stdio.h>
int main(){
double f;
scanf("%lf",&f);
printf("%.5f",(f-32)/9*5);
return 0;
}

0023 .  与圆相关的计算(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9
#include<stdio.h>
#define PI 3.14159
int main()
{
double r;
scanf("%lf",&r);
printf("%.4f %.4f %.4f",2*r,2*PI*r,PI*r*r);
return 0;
}

0025 .  计算浮点数相除的余数(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int main()
{
double a,b,sum;
int k;    
scanf("%lf %lf",&a,&b);
k = a / b;
sum =a - k * b;
printf("%.6f",sum);
return 0;
}

0026.  计算球的体积(c语言入门练习题)

图片

1
2
3
4
5
6
7
8
9
#include<stdio.h>
#define PI 3.14
int main()
{
    double r;
    scanf("%lf",&r);
    printf("%.2f",4.0/3*PI*r*r*r);
    return 0;
}

0027.  温度表达转化(c语言入门练习题)

图片

图片

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int main()
{
int cnt = 1, h, r;
    scanf("%d %d",&h, &r);
double v = 3.14159 * h * r * r;
while((cnt * v) < 20000)
cnt ++;
printf("%d", cnt);
return 0;
}

第一天开始正式的复健吧,算是很基础的题,用来熟悉下语法或者一些小细节,闲下来可以继续刷,主要还得看看课以及其他事。